﻿using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;

namespace INNOVACALL.Framework.Common.Extensions
{
    public static class XmlExtension
    {
        public static string GetXPath(this System.Xml.Linq.XElement node)
        {
            string temp = null;
            System.Xml.Linq.XElement sibling = null;
            int previousSiblings = 1;
            //I dont want to know that it was a generic document

            sibling = node.PreviousNode as XElement;
            //Perculate up getting the count of all of this node's sibling before it. 
            while (sibling != null)
            {
                //Only count if the sibling has the same name as this node 
                if (sibling.Name == node.Name)
                {
                    previousSiblings += 1;
                }
                sibling = sibling.PreviousNode as XElement;
            }
            //Mark this node's index, if it has one 
            // Also mark the index to 1 or the default if it does have a sibling just no previous. 
            temp = node.Name + (previousSiblings > 0 || node.NextNode != null ? "[" + previousSiblings.ToString() + "]" : "").ToString();
            if (node.Parent != null)
            {
                return GetXPath(node.Parent) + "/" + temp;
            }
            return temp;
        }
        public static string IndentXMLString(this string xml)
        {
            string outXml = string.Empty;
            MemoryStream ms = new MemoryStream();
            // Create a XMLTextWriter that will send its output to a memory stream (file)
            XmlTextWriter xtw = new XmlTextWriter(ms, Encoding.Unicode);
            XmlDocument doc = new XmlDocument();

            try
            {
                // Load the unformatted XML text string into an instance 
                // of the XML Document Object Model (DOM)
                doc.LoadXml(xml);

                // Set the formatting property of the XML Text Writer to indented
                // the text writer is where the indenting will be performed
                xtw.Formatting = Formatting.Indented;

                // write dom xml to the xmltextwriter
                doc.WriteContentTo(xtw);
                // Flush the contents of the text writer
                // to the memory stream, which is simply a memory file
                xtw.Flush();

                // set to start of the memory stream (file)
                ms.Seek(0, SeekOrigin.Begin);
                // create a reader to read the contents of 
                // the memory stream (file)
                StreamReader sr = new StreamReader(ms);
                // return the formatted string to caller
                return sr.ReadToEnd();
            }
            catch (Exception ex)
            {
                return xml;
            }
        }
        public static string RemoveSpaceBeetweenTags(this string xmlString) {
            if (!string.IsNullOrEmpty(xmlString))
            {
                Regex regex = new Regex(@">\s*<");
                return regex.Replace(xmlString, "><");
            }
            else
            {
                return xmlString;
            }
        }
        public static string GetXPath(this System.Xml.Linq.XAttribute attribute)
        {
            return attribute.Parent.GetXPath() + "@" + attribute.Name;
        }

        public static string GetXPath(this System.Xml.XmlNode node)
        {
            string temp = null;
            System.Xml.XmlNode sibling = null;
            int previousSiblings = 1;
            //I dont want to know that it was a generic document 
            if (node.Name == "#document")
                return "";
            //Prime it 
            sibling = node.PreviousSibling;
            //Perculate up getting the count of all of this node's sibling before it. 
            while (sibling != null)
            {
                //Only count if the sibling has the same name as this node 
                if (sibling.Name == node.Name)
                {
                    previousSiblings += 1;
                }
                sibling = sibling.PreviousSibling;
            }
            //Mark this node's index, if it has one 
            // Also mark the index to 1 or the default if it does have a sibling just no previous. 
            temp = node.Name + (previousSiblings > 0 || node.NextSibling != null ? "[" + previousSiblings.ToString() + "]" : "").ToString();
            if (node.ParentNode != null)
            {
                return GetXPath(node.ParentNode) + "/" + temp;
            }
            return temp;
        }

        public static T Deserialize<T>(this XDocument document) where T : class
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
            MemoryStream memStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(document.ToString()));
            return xmlSerializer.Deserialize(memStream) as T;
        }

        public static string ToXmlStringFormat(this DateTime dt)
        {
            return dt.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'ff");
        }

        public static DateTime XmlDateStringToDateTime(this string dt)
        {
            return DateTime.ParseExact(dt, "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'ff", System.Globalization.CultureInfo.CurrentCulture);
        }

        /// <summary>
        /// Convertit un XmlDocument en XDocument
        /// </summary>
        /// <param name="doc"></param>
        /// <returns></returns>
        public static XDocument XmlDocumentToXDocument(XmlDocument doc)
        {
            return XDocument.Parse(doc.OuterXml);
        }
        public static XmlDocument XDocumentToXmlDocument(XDocument doc)
        {
            XmlDocument toReturn = new XmlDocument();
            toReturn.LoadXml(doc.ToString());
            return toReturn;
        }
        public static XElement GetXElement(this XmlNode node)
        {
            XDocument xDoc = new XDocument();
            using (XmlWriter xmlWriter = xDoc.CreateWriter())
                node.WriteTo(xmlWriter);
            return xDoc.Root;
        }

        public static XmlNode GetXmlNode(this XElement element)
        {
            using (XmlReader xmlReader = element.CreateReader())
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(xmlReader);
                return xmlDoc;
            }
        }

        public static string RemovePrefixes(this string strXmlWorkorderPart)
        {
            string toReturn = strXmlWorkorderPart;
            //Balises d'ouverture
            Regex oRegex = new Regex("<(?<Prefix>...):", RegexOptions.IgnoreCase);
            MatchCollection matches = oRegex.Matches(toReturn);
            foreach (Match match in matches)
            {
                string Prefix = match.Groups["Prefix"].Value;
                toReturn = toReturn.Replace(match.Value, string.Format(@"<{0}_", Prefix));
            }
            //Balises de fermeture
            oRegex = new Regex("</(?<Prefix>...):", RegexOptions.IgnoreCase);
            matches = oRegex.Matches(toReturn);
            foreach (Match match in matches)
            {
                string Prefix = match.Groups["Prefix"].Value;
                toReturn = toReturn.Replace(match.Value, string.Format(@"</{0}_", Prefix));
            }
            return toReturn;
        }
        /// <summary>
        /// Reconstruction des préfixes xml
        /// </summary>
        /// <param name="strXmlWorkorderPart"></param>
        /// <returns></returns>
        public static string RestorePrefixes(string strXmlWorkorderPart)
        {
            string toReturn = strXmlWorkorderPart;
            //Balises d'ouverture
            Regex oRegex = new Regex("<(?<Prefix>...)_", RegexOptions.IgnoreCase);
            MatchCollection matches = oRegex.Matches(toReturn);
            foreach (Match match in matches)
            {
                string Prefix = match.Groups["Prefix"].Value;
                toReturn = toReturn.Replace(match.Value, string.Format(@"<{0}:", Prefix));
            }
            //Balises de fermeture
            oRegex = new Regex("</(?<Prefix>...)_", RegexOptions.IgnoreCase);
            matches = oRegex.Matches(toReturn);
            foreach (Match match in matches)
            {
                string Prefix = match.Groups["Prefix"].Value;
                toReturn = toReturn.Replace(match.Value, string.Format(@"</{0}:", Prefix));
            }
            return toReturn;
        }
    }
}
